/**
 * vue项目所有文件命名全部采用中划线分隔   groupUtils
 * 创建时间：2021/6/3 11:50
 */
import typeOfUtils from "@/utils/type-of-utils";
import {deepClone} from "@/utils/index";

const selfUtils = {
  // 求差集
  differenceSet(source, target, optionsAreEqual) {
    const result = []
    source.forEach((i, index) => {
      const find = target.find(j => optionsAreEqual(i, j))
      if (typeOfUtils.isEmpty(find)) {
        result.push({
          index: index,
          data: i
        })
      }
    })
    return result
  }
}

const groupUtils = {
  /**
   *const group = groupUtils.group(res.data,(item) => {
          return item.projectCity
        },(item,mapItem) => {
          return mapItem === item.projectCity
        })
   console.log(group);
   * @param list {[any]}
   * @param mapMethod {Function} 就是数组遍历的map函数,返回的值用于第三个回调函数的第二个参数使用
   * @param findIndexMethod {Function} 参数(item,mapItem),返回值决定这个item加入那个分组
   * @return {[[
        {
          index: Number,
          data: any,
          groupData: any
        }
   * ]]}
   */
  group(list, mapMethod, findIndexMethod) {
    if (typeOfUtils.isNotArray(list)) {
      throw new Error('list数据错误')
    }
    if (typeOfUtils.isNotFunction(mapMethod)) {
      throw new Error('mapMethod数据错误')
    }
    if (typeOfUtils.isNotFunction(findIndexMethod)) {
      throw new Error('findIndexMethod数据错误')
    }
    const buildingCodeSet = Array.from(new Set(list.map(mapMethod)))
    const group = []
    buildingCodeSet.forEach(i => {
      group.push([])
    })
    // 进行分组
    list.forEach((i, index) => {
      const groupIndex = buildingCodeSet.findIndex(j => findIndexMethod(i, j))
      group[groupIndex].push({
        index: index,
        data: i,
        groupData: buildingCodeSet[groupIndex]
      })
    })
    return group
  },
  /**
   * @description 两个数组进行合并
   * @description 在source中多的添加到target
   * @description 在source少的target要去除
   * @param source {Array} 遍历数组
   * @param target {Array} 查找数组
   * @param optionsAreEqual {Function} 判断两个对象是否相等 参数: (sourceItem,targetItem):Boolean
   * @param objectMerge {Function} 合并相同数据,默认把source合并到target 参数: (sourceItem,targetItem):Object
   * @param saveSourceOther {Boolean} 是否保留source多的数据
   * @param saveTargetOther {Boolean} 是否保留target多的数据
   * @return {Array}
   */
  listMergeList(
    source,
    target,
    optionsAreEqual,
    objectMerge,
    saveSourceOther = false,
    saveTargetOther = false,
  ) {
    let result = []
    if (typeOfUtils.isEmpty(target)) {
      return deepClone(source)
    }
    const indexResult = []
    if (typeOfUtils.isEmpty(objectMerge) || typeOfUtils.isNotFunction(objectMerge)) {
      objectMerge = (source1, find) => {
        return Object.assign(deepClone(source1), find)
      }
    }
    // 先求出交集,交集这里已经完全处理出target少的数据
    source.forEach((i, index) => {
      const find = target.find(j => optionsAreEqual(i, j))
      if (typeOfUtils.isNotEmpty(find)) {
        indexResult.push({
          index: index,
          data: objectMerge(i, find)
        })
      }
    })
    // 求差集
    // 保留source多的数据
    if (saveSourceOther) {
      // 求出source多的数据,也就是去找target里面没有的,然后加入
      indexResult.push(...selfUtils.differenceSet(source, target, optionsAreEqual))
    }
    // 保留target多的数据
    if (saveTargetOther) {
      // 求出target多的数据,也就是去找source里面没有的,然后加入
      indexResult.push(...selfUtils.differenceSet(target, source, optionsAreEqual))
    }
    result = indexResult.sort((a, b) => a.index - b.index).map(i => i.data)
    return result
  }
}

export default groupUtils
